﻿#region Opis pliku
//-----------------------------------------------------------------------------
// Menu.cs
// Autor: Jan Czarnowski
// 9.11.2012
//-----------------------------------------------------------------------------
#endregion

#region Using...

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Diagnostics;
using System.Collections.Generic;
using System;

#endregion

namespace pogra
{
    /// <summary>
    /// Klasa abstrakcyjna, implementująca podstawowe
    /// zachowanie każdego menu gry. Aby dodać nowe
    /// menu, należy odziedziczyć z tej klasy i 
    /// nadpisać metodę LoadContent, HandleInput 
    /// i handleButtons()
    /// </summary>
    public class Menu : GameScreen
    {
        #region pola

        protected string title = "title";
        protected Rectangle menuRect = new Rectangle(0, 0, 200, 300);
        protected Rectangle dragRect = new Rectangle(0, 0, 200, 20);

        protected Color bgColor = Color.LightGray;
        protected Color daColor = Color.Blue;
        protected Color bdColor = Color.Black;

        protected List<MenuItem> itemList = new List<MenuItem>();

        protected bool isMovable = true;

        private Point dragClickDelta = Point.Zero;
        private bool isBeingDragged = false;
        protected bool loaded = false;
        
        public Rectangle Bounds
        {
            get { return menuRect; }
        }

        public Vector2 Pos
        {
            get { return new Vector2(menuRect.X, menuRect.Y); }
            set
            {
                menuRect.X = (int)value.X; 
                menuRect.Y = (int)value.Y;
                dragRect.X = menuRect.X; 
                dragRect.Y = menuRect.Y;

                for(int i = 0; i < itemList.Count; ++i)
                    itemList[i].Bounds = new Rectangle(menuRect.X, dragRect.Bottom + i * itemList[i].Bounds.Height, itemList[i].Bounds.Width, itemList[i].Bounds.Height);
                
            }
        }

        #endregion

        #region metody draw i update

        public override void Draw(GameTime gameTime)
        {
            if (!loaded)
                return;

            ExtendedSpriteBatch exSpriteBatch = ScreenManager.ExtendedSpriteBatch;
            exSpriteBatch.End();

            exSpriteBatch.Begin();

            // cień
            exSpriteBatch.FillRectangle(new Rectangle(menuRect.X + 10, menuRect.Y + 10, menuRect.Width, menuRect.Height), Color.Black * 0.1f);

            // glowne prostokaty
            exSpriteBatch.FillRectangle(menuRect, bgColor);
            exSpriteBatch.FillRectangle(dragRect, daColor);

            // rysowanie ramki
            exSpriteBatch.DrawLine(new Vector2(menuRect.Left, menuRect.Top), new Vector2(menuRect.Left, menuRect.Bottom), bdColor);
            exSpriteBatch.DrawLine(new Vector2(menuRect.Left, menuRect.Bottom), new Vector2(menuRect.Right, menuRect.Bottom), bdColor);
            exSpriteBatch.DrawLine(new Vector2(menuRect.Right, menuRect.Bottom), new Vector2(menuRect.Right, menuRect.Top), bdColor);
            exSpriteBatch.DrawLine(new Vector2(menuRect.Right, menuRect.Top), new Vector2(menuRect.Left, menuRect.Top), bdColor);
            exSpriteBatch.DrawLine(new Vector2(dragRect.Left, dragRect.Bottom), new Vector2(dragRect.Right, dragRect.Bottom), bdColor);

            // tytuł okna
            Vector2 position;
            position.X = dragRect.Center.X - ScreenManager.Font.MeasureString(title).X / 2;
            position.Y = dragRect.Center.Y - ScreenManager.Font.MeasureString(title).Y / 2;
            exSpriteBatch.DrawString(ScreenManager.Font, title, position, Color.Black);

            foreach (MenuItem item in itemList)
                item.Draw(exSpriteBatch);

            exSpriteBatch.End();

            RTSGame game = ((RTSGame) ScreenManager.Game);
                
            exSpriteBatch.Begin(SpriteSortMode.Deferred,
                            BlendState.AlphaBlend,
                            null,
                            null,
                            null,
                            null,
                            game.Camera.GetTransformation(game.GraphicsDevice));
        }

        public override void Update(GameTime gameTime)
        {
                dragRect.X = menuRect.X;
                dragRect.Y = menuRect.Y;

                foreach (MenuItem item in itemList)
                {
                    item.Update(gameTime);

                    if (item.IsPressed)
                        handleButtons(item.Text);
                } 
        }

        #endregion

        #region metody protected

        protected virtual void handleButtons(string pressedText)
        {

        }

        #endregion

        #region metody publiczne

        /// <summary>
        /// Obsługa urządzeń wejścia
        /// </summary>
        /// <param name="input"></param>
        public override void HandleInput(InputState input, bool otherScreenHasFocus, ref bool eventHandled)
        {
            RTSGame game = (RTSGame)ScreenManager.Game;

            // transformujemy pozycje myszki
            Point mousePos = new Point(input.CurrentMouseState.X, input.CurrentMouseState.Y);
            Point mousePos_t = game.Camera.transformPoint(mousePos, game.GraphicsDevice);

            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;

            // jeżeli kliknięcie nastąpiło w menu, niech tło już go nie obsluguje
            Rectangle temp = menuRect;

            if (menuRect.Contains(mousePos) && input.IsNewMLeftButtonPressed())
                eventHandled = true;

            // obsluga poruszania oknem
            if(isMovable)
            {
                // czy rozpoczęto ciągnięcie okna?
                if (input.IsNewMLeftButtonPressed() && dragRect.Contains(mousePos))
                {
                    isBeingDragged = true;
                    dragClickDelta.X = mousePos.X - menuRect.X;
                    dragClickDelta.Y = mousePos.Y - menuRect.Y;
                }

                // czy zakończono ciągnięcie okna
                if (input.WasMLeftButtonReleased())
                    isBeingDragged = false;

                // jeżeli okno jest ciągnięte, aktualizuj pozycję
                if (isBeingDragged && viewport.Bounds.Contains(mousePos))
                {
                    menuRect.X = mousePos.X - dragClickDelta.X;
                    menuRect.Y = mousePos.Y - dragClickDelta.Y;
                    dragRect.X = menuRect.X;
                    dragRect.Y = menuRect.Y;
                }
            }

            for (int i = 0; i < itemList.Count; ++i)
            {
                // ustawianie nowyh pozycji elementów
                itemList[i].Bounds = new Rectangle(menuRect.X, dragRect.Bottom + i * itemList[i].Bounds.Height,
                                                    itemList[i].Bounds.Width, itemList[i].Bounds.Height);

                itemList[i].HandleInput(input);
            }
        }

        #endregion
    }
}
